package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.RoomInfoMapper;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.room.RoomDetailVo;
import com.atguigu.lease.web.admin.vo.room.RoomItemVo;
import com.atguigu.lease.web.admin.vo.room.RoomQueryVo;
import com.atguigu.lease.web.admin.vo.room.RoomSubmitVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * @author xiongkunYang
 * @description 针对表【room_info(房间信息表)】的数据库操作Service实现
 * @createDate 2025-04-19 22:27:34
 */
@Service
@RequiredArgsConstructor
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo>
        implements RoomInfoService {
    private final RoomInfoMapper roomInfoMapper;
    private final GraphInfoService graphInfoService;
    private final RoomAttrValueService roomAttrValueService;
    private final RoomFacilityService roomFacilityService;
    private final RoomLabelService roomLabelService;
    private final RoomPaymentTypeService roomPaymentTypeService;
    private final RoomLeaseTermService roomLeaseTermService;
    private final RedisTemplate<String, Object> redisTemplate;


    /**
     * 保存或更新房间信息。
     * 根据传入的房间提交对象（RoomSubmitVo）执行以下操作：
     * 1. 调用父类的 saveOrUpdate 方法保存或更新房间基本信息。
     * 2. 如果房间 ID 存在，则删除与该房间相关的所有关联数据（如图片、属性、配套、标签等）。
     * 3. 根据 RoomSubmitVo 中的数据，重新插入新的关联数据。
     *
     * @param roomSubmitVo 房间提交对象，包含房间的基本信息及关联数据（如图片列表、属性列表等）。
     *                     - id: 房间 ID，如果为 null 表示新增房间，否则表示更新现有房间。
     *                     - graphVoList: 房间图片列表。
     *                     - attrValueIds: 房间属性值 ID 列表。
     *                     - facilityInfoIds: 房间配套信息 ID 列表。
     *                     - labelInfoIds: 房间标签信息 ID 列表。
     *                     - paymentTypeIds: 房间支付方式 ID 列表。
     *                     - leaseTermIds: 房间租赁期 ID 列表。
     */
    @Override
    public Boolean saveOrUpdateRoomSubmit(RoomSubmitVo roomSubmitVo) {
        Long roomId = roomSubmitVo.getId();
        boolean isSaveOrUpdate = super.saveOrUpdate(roomSubmitVo);

        // 如果房间 ID 存在，删除与该房间相关的所有旧数据
        if (roomId != null) {
            this.removeRoomRelatedData(roomId);
        }

        // 插入新的房间图片列表
        Optional.ofNullable(roomSubmitVo.getGraphVoList())
                .filter(graphVos -> !graphVos.isEmpty())
                .map(graphVos -> graphVos.stream()
                        .map(graphVo -> GraphInfo.builder()
                                .name(graphVo.getName()).url(graphVo.getUrl()).itemType(ItemType.ROOM).itemId(roomSubmitVo.getId())
                                .build())
                        .toList())
                .ifPresent(this.graphInfoService::saveBatch);

        // 插入新的房间属性值列表
        Optional.ofNullable(roomSubmitVo.getAttrValueIds())
                .filter(attrValueIds -> !attrValueIds.isEmpty())
                .map(attrValueIds -> attrValueIds.stream()
                        .map(attrValueId -> RoomAttrValue.builder()
                                .roomId(roomSubmitVo.getId()).attrValueId(attrValueId)
                                .build())
                        .toList())
                .ifPresent(this.roomAttrValueService::saveBatch);

        // 插入新的房间配套信息列表
        Optional.ofNullable(roomSubmitVo.getFacilityInfoIds())
                .filter(facilityInfoIds -> !facilityInfoIds.isEmpty())
                .map(facilityInfoIds -> facilityInfoIds.stream()
                        .map(facilityInfoId -> RoomFacility.builder()
                                .roomId(roomSubmitVo.getId()).facilityId(facilityInfoId)
                                .build())
                        .toList())
                .ifPresent(this.roomFacilityService::saveBatch);

        // 插入新的房间标签信息列表
        Optional.ofNullable(roomSubmitVo.getLabelInfoIds())
                .filter(labelInfoIds -> !labelInfoIds.isEmpty())
                .map(labelInfoIds -> labelInfoIds.stream()
                        .map(labelInfoId -> RoomLabel.builder()
                                .roomId(roomSubmitVo.getId()).labelId(labelInfoId)
                                .build())
                        .toList())
                .ifPresent(this.roomLabelService::saveBatch);

        // 插入新的房间支付方式列表
        Optional.ofNullable(roomSubmitVo.getPaymentTypeIds())
                .filter(paymentTypeIds -> !paymentTypeIds.isEmpty())
                .map(paymentTypeIds -> paymentTypeIds.stream()
                        .map(paymentTypeId -> RoomPaymentType.builder()
                                .roomId(roomSubmitVo.getId()).paymentTypeId(paymentTypeId)
                                .build())
                        .toList())
                .ifPresent(this.roomPaymentTypeService::saveBatch);

        // 插入新的房间租赁期列表
        Optional.ofNullable(roomSubmitVo.getLeaseTermIds())
                .filter(leaseTermIds -> !leaseTermIds.isEmpty())
                .map(leaseTermIds -> leaseTermIds.stream()
                        .map(leaseTermId -> RoomLeaseTerm.builder()
                                .roomId(roomSubmitVo.getId()).leaseTermId(leaseTermId)
                                .build())
                        .toList())
                .ifPresent(this.roomLeaseTermService::saveBatch);

        return isSaveOrUpdate;
    }

    @Override
    public IPage<RoomItemVo> roomItemPageByQuery(long current, long size, RoomQueryVo queryVo) {
        Page<RoomItemVo> page = new Page<>(current, size);
        return this.roomInfoMapper.selectRoomItemPageByQuery(page, queryVo);
    }

    @Override
    public RoomDetailVo getRoomDetailById(Long id) {
        return this.roomInfoMapper.selectRoomDetailById(id);
    }

    @Override
    public Boolean removeRoomInfoById(Long id) {
        this.removeRoomRelatedData(id);
        return super.removeById(id);
    }

    /**
     * 删除与房间相关的所有关联数据。
     *
     * @param roomId 房间ID
     */
    private void removeRoomRelatedData(Long roomId) {
        this.graphInfoService.remove(
                new LambdaQueryWrapper<GraphInfo>()
                        .eq(GraphInfo::getItemType, ItemType.ROOM)
                        .eq(GraphInfo::getItemId, roomId));
        this.roomAttrValueService.remove(
                new LambdaQueryWrapper<RoomAttrValue>()
                        .eq(RoomAttrValue::getRoomId, roomId));
        this.roomFacilityService.remove(
                new LambdaQueryWrapper<RoomFacility>()
                        .eq(RoomFacility::getRoomId, roomId));
        this.roomLabelService.remove(
                new LambdaQueryWrapper<RoomLabel>()
                        .eq(RoomLabel::getRoomId, roomId));
        this.roomPaymentTypeService.remove(
                new LambdaQueryWrapper<RoomPaymentType>()
                        .eq(RoomPaymentType::getRoomId, roomId));
        this.roomLeaseTermService.remove(
                new LambdaQueryWrapper<RoomLeaseTerm>()
                        .eq(RoomLeaseTerm::getRoomId, roomId));
        // 删除redis缓存
        this.redisTemplate.delete(RedisConstant.APP_ROOM_PREFIX + roomId);
    }
}




